<?php
declare(strict_types=1);
namespace Framework\Support;

class Upload
{
	protected static \OSS\OssClient $auth;
	protected static int $type=1;

    /**
     * @return \OSS\OssClient
     */
	public static function autoInfo():\OSS\OssClient
	{
        empty(self::$auth) && self::$auth = new \OSS\OssClient(_CONF('OssAccessKey'), _CONF('OssSecretKey'), _CONF('OssEndpoint'));
		return self::$auth;
	}

    /**
     * @param $url
     * @param $first
     * @param string $header
     * @param string $user_agent
     * @param int $timeout
     * @return array|null
     * @throws Exception
     */
	public static function get_image(string $url,string $first, string $header = '', string $user_agent = '', int $timeout=30 ): ?array
    {
		$data= https_get($url,$header,$user_agent,$timeout);
		$u = explode('/',$url);
		$ext  = explode('.',end($u));
		$ext = end($ext);
		$attach = _SYS('Attach');
		$file['name'] = md5($url).'.'.$ext;
		if (!xn_in_array($ext, $attach['image'])) {
			$file['name'] = md5($url).'.png';
		}
		$file['tmp_name']=__WEBDIR__.$file['name'];
		file_put_contents($file['tmp_name'],$data);
		return self::upload_file($file,$first);
	}


    /**
     * @param $file
     * @param $first
     * @param int $max_width
     * @return array|null
     * @throws Exception
     */
	public static function upload_file(array $file,string $first, $max_width=1024): ?array
    {
        try {
            $_filename = self::filename($file, $first);
        } catch (\Exception $e) {
            throw new \Exception('文件创建失败',500);
        }
        $size = getimagesize($file['tmp_name'],$info);
        $ret=false;
		if($size){
            $width=(int)$size[0];
            $height=(int)$size[1];
			if($width>$max_width){
				$n_w=(int)$max_width;
				$n_h=(int)$height*($max_width/$width);
                $width=$n_w;
                $height=$n_h;
				$size=getimagesize($file['tmp_name']);
				switch($size[2]){
					case 2:
						$new=imagecreatetruecolor((int)$n_w, (int)$n_h);
						$img=imagecreatefromjpeg($file['tmp_name']);
						imagecopyresized($new, $img,0, 0,0, 0,(int)$n_w, (int)$n_h, (int)$width, (int)$height);
						imagejpeg($new, $file['tmp_name']);
						imagedestroy($new);
						imagedestroy($img);
						break;
					case 3:
						$new=imagecreatetruecolor((int)$n_w, (int)$n_h);
						$img=imagecreatefrompng($file['tmp_name']);
						imagecopyresized($new, $img,0, 0,0, 0,(int)$n_w, (int)$n_h, (int)$width, (int)$height);
						imagepng($new, $file['tmp_name']);
						imagedestroy($new);
						imagedestroy($img);
						break;
					default:
				}
			}
        }
        $ret = copy($file['tmp_name'], __WEBDIR__ . $_filename['Name']);
        xn_unlink($file['tmp_name']);
		$auto = self::autoInfo();
		switch (self::$type) {
			case 1://阿里oss
				$ret = $auto->uploadFile(_CONF('OssBucket'), $_filename['Name'], __WEBDIR__ . $_filename['Name']);
				break;
			default:
		}
		$_filename['Spec'] = $width.'*'.$height;
		$_filename['is_upload'] = $ret;
		return $_filename;
	}

    /**
     * @param $filename
     * @return array
     * @throws \OSS\Core\OssException
     * @throws \OSS\Http\RequestCore_Exception
     */
	public static function upload_file_byname(string $filename): array
    {
		$auto = self::autoInfo();
		$file_name= str_replace(__WEBDIR__,'',$filename);
		//var_dump($filename);
        $ret = $auto->uploadFile(_CONF('OssBucket'), $file_name, $filename);
		$_filename['is_upload'] = $ret;
		return $_filename;
	}

    /**
     * @param $filetype
     * @param $file
     * @param $id
     * @param $cover
     * @param $max_width
     * @return array
     * @throws \OSS\Core\OssException
     * @throws \OSS\Http\RequestCore_Exception
     */
	public static function upload_by_id(string $filetype,array $file,string $id,bool $cover,int $max_width=1024): array
    {
		$_filename = self::filename_by_id($filetype, $file, $id,$cover);
		list($width, $height)=getimagesize($file['tmp_name']);
		if($width>$max_width){
			$n_w=$max_width;
			$n_h=$height*($max_width/$width);
			$size=getimagesize($file['tmp_name']);
			switch($size[2]){
				case 2:
					$new=imagecreatetruecolor($n_w, $n_h);
					$img=imagecreatefromjpeg($file['tmp_name']);
					imagecopyresized($new, $img,0, 0,0, 0,$n_w, $n_h, $width, $height);
					imagejpeg($new, $file['tmp_name']);
					imagedestroy($new);
					imagedestroy($img);
					break;
				case 3:
					$new=imagecreatetruecolor($n_w, $n_h);
					$img=imagecreatefrompng($file['tmp_name']);
					imagecopyresized($new, $img,0, 0,0, 0,$n_w, $n_h, $width, $height);
					imagepng($new, $file['tmp_name']);
					imagedestroy($new);
					imagedestroy($img);
					break;
				default:
			}
        }
        copy($file['tmp_name'], __WEBDIR__ . $_filename['Name']);
        xn_unlink($file['tmp_name']);
		if($cover){
		    self::delete_file($_filename['Name']);
        }
        $auto = self::autoInfo();
        $ret=false;
        $ret = $auto->uploadFile(_CONF('OssBucket'), $_filename['Name'], __WEBDIR__ . $_filename['Name']);
		$_filename['filesize'] =  filesize(__WEBDIR__ . $_filename['Name']);
		$_filename['is_upload'] = $ret;
		return $_filename;
	}

    /**
     * @param $filetype
     * @param $id
     * @param $ext
     * @param int $type
     * @return string
     */
	public static function delete_file(string $filename): ?array
    {
        xn_unlink(__WEBDIR__ . $filename);
        return self::autoInfo()->deleteObject(_CONF('OssBucket'), $filename);
	}


    // 获取安全的文件名，如果文件存在，则加时间戳和随机数，避免重复
    /**
     * @param string $filename
     * @param string $dir
     * @param bool $cover
     * @return string
     */
	public static function image_safe_name(string $filename,string $dir,bool $cover = false): string
    {
		$attach = _SYS('Attach');
		$time = time();
		// 最后一个 . 保留，其他的 . 替换
		$s1 = substr($filename, 0, strrpos($filename, '.'));
		$s2 = substr(strrchr($filename, '.'), 1);
		!xn_in_array($s2, $attach['all']) AND $s2 = '_' . $s2;
		if (is_file($dir . $s1.'.'.$s2) && !$cover) {
			$rename = $s1 . $time . rand(11111, 99999) . '.' . $s2;
		} else {
			$rename = $s1.'.'.$s2;
		}
		return $rename;
	}

    /**
     * @param array $file
     * @param string $first
     * @return array
     * @throws \Exception
     */
	public static function filename(array $file,string $first): array
    {
		$attach = _SYS('Attach');
		mt_srand();
		$dir = date('Y/m/d/');
		$ext = self::file_ext($file['name']);
		if (xn_in_array(strtolower($ext), $attach['image'])) {
			$s = file_read($file['tmp_name']);
			if (stripos($s, '<script') !== FALSE || stripos($s, '<?php') !== FALSE || !$s) {
				throw new \Exception('图片不安全',500);
			}
		}
		$name = $first . '.' . $ext;
		$dotfile = self::image_safe_name($name, __WEBDIR__ . $dir,false);
		$url = '/' . $dir . $dotfile;
		!is_dir(dirname(__WEBDIR__ . $dir.$name)) AND mkdir(dirname(__WEBDIR__ . $dir.$name), 0777, true);
		return ['Patch' => $url, 'Name' => $dir . $dotfile,'Ext'=>$ext];
	}

    /**
     * @param string $filetype
     * @param string $id
     * @param string $ext
     * @param int $type
     * @return string
     */
	public static function get_filename_by_id(string $filetype,string $id,string $ext,int $type=1): string
    {
		$_id = sprintf("%09d", $id);
		$s1 = substr($_id, 0, 3);
		$s2 = substr($_id, 3, 3);
		$dir = "{$filetype}/{$s1}/{$s2}/";
		$name = $id . '.' . $ext;
		$data=['/' . $dir . $name, _CONF('OssHost').'/' .$dir . $name];
		return $data[$type];
	}

    /**
     * @param string $filetype
     * @param array $file
     * @param string $id
     * @param bool $cover
     * @return array
     */
	public static function filename_by_id(string $filetype,array $file,string $id,bool $cover): array
    {
		$attach = _SYS('Attach');
		mt_srand();
		$_id = sprintf("%09d", $id);
		$s1 = substr($_id, 0, 3);
		$s2 = substr($_id, 3, 3);
		$dir = "$filetype/$s1/$s2/";
		$ext = self::file_ext($file['name']);
		if (xn_in_array($ext, $attach['image'])) {
			$s = file_read($file['tmp_name']);
			if (stripos($s, '<script') !== FALSE || stripos($s, '<?php') !== FALSE || !$s) {
				throw new \Exception('图片不安全');
			}
		}
		$name = $id . '.' . $ext;
		$dotfile = self::image_safe_name($name, __WEBDIR__ . $dir,$cover);
		$url = '/' . $dir . $name;
		!is_dir(__WEBDIR__ . $dir) AND mkdir(__WEBDIR__ . $dir, 0777, true);
		return ['Patch' => $url, 'Name' => $dir . $dotfile,'Ext'=>$ext];
	}

    /**
     * @param string $filename
     * @param int $max
     * @return string
     */
	public static function file_ext(string $filename,int $max = 16): string
    {
		$ext = strtolower(substr(strrchr($filename, '.'), 1));
		$ext = xn_urlencode($ext);
		strlen($ext) > $max AND $ext = substr($ext, 0, $max);
		if (!preg_match('#^\w+$#', $ext)) $ext = 'attach';
		return $ext;
	}
}
?>